package com.own.demo.建筑物;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.own.demo.utils.CommWriterFileInfo;
import com.own.demo.utils.FileToStringUtils;
import com.own.demo.utils.GeoTools;
import com.own.demo.utils.geo.PoiTypeEnums;
import com.own.demo.utils.geo.buffer.LineBufferImpl;
import com.own.demo.utils.geo.buffer.PolygonBufferImpl;
import com.own.demo.vo.Bounds;
import lombok.SneakyThrows;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;

import java.io.BufferedWriter;
import java.io.File;
import java.util.*;

public class 长沙市区域加建筑物 {
    //边界
    public static long indexPointIdIndex = 1;

    static int HEIGHT = 100;
    static int AREA = 1;
    static LineBufferImpl defaultBuffer = (LineBufferImpl) PoiTypeEnums.POLYLINE.getBufferUtil();
    static PolygonBufferImpl polygonBuffer = new PolygonBufferImpl();

    static String buld = "112.671689,28.246673;112.750619,28.295456;112.836473,28.239354;112.826780,28.166133;112.727078,28.150262;112.632916,28.164912;112.671689,28.246673&113.722709,28.356403;113.823796,28.347873;113.809948,28.26131;113.724094,28.313744;113.722709,28.356403";
    static List<Geometry> listBuildInfo = new ArrayList();

    public static void main(String[] args) {
        JSONObject jsonObject = getArea();
        if (jsonObject != null) {
            String json = jsonObject.toJSONString();
            writerFoFile("var polylineData1 = " + json);
        }
    }

    public static JSONObject getArea() {
        System.out.println("开始执行");
        File geoZJ = new File("E:\\ownCode\\emg-geojson\\src\\test\\java\\com\\own\\demo\\geodemo\\device.txt");
        String geoData = FileToStringUtils.txt2String(geoZJ).split("\\|")[0];
        String[] adasStr = geoData.split("\\,");
        int row = adasStr.length;
        System.out.println("行政区域围栏点数量：" + row);


        String[] build = buld.split("&");
        int buildRow = build.length;
        for (int i = 0; i < buildRow; i++) {
            String pointInfo = build[i];
            listBuildInfo.add(polygonBuffer.geometrySplit(pointInfo));
        }


        List<Double> lonList = new ArrayList(100000);
        List<Double> latList = new ArrayList(100000);

        for (int i = 0; i < row; i++) {
            String[] points = adasStr[i].split(" ");
            int pointLength = points.length;
            if (pointLength > 2) {
                System.out.println("错误采集点");
                continue;
            }

            lonList.add(Double.valueOf(points[0]));
            latList.add(Double.valueOf(points[1]));
        }

        System.out.println("lon长度" + lonList.size());
        System.out.println("lat长度" + latList.size());

        double minLon = Collections.min(lonList);
        double maxLon = Collections.max(lonList);
        double minLat = Collections.min(latList);
        double maxLat = Collections.max(latList);
        Bounds bounds = new Bounds(minLon, maxLon, minLat, maxLat);
        try {
            Geometry geometry = PoiTypeEnums.geometry(geoData, PoiTypeEnums.POLYGON.getCode());
            return 长沙市区域加建筑物.goGeoJSONV2(geometry, bounds, true, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param geometry 全量边界
     * @param bounds
     * @param flag     false 只生成边界数据。 不生成osm文件  true 全量生成
     * @return
     */
    @SneakyThrows
    public static JSONObject goGeoJSONV2(Geometry geometry, Bounds bounds, boolean flag, boolean isDelArea) {
        if (geometry == null) {
            return null;
        }
        List<Coordinate> listAll = Arrays.asList(geometry.getCoordinates());
        JSONObject jsonObject = dataDraw(new ArrayList<>(), bounds, new ArrayList<>(), flag, isDelArea);
        jsonObject.put("bounds", bounds);
        jsonObject.getJSONArray("features").addAll(setXYGeo(0, 0, listAll, "LineString"));

        Map<Integer, JSONArray> build = 建筑物统计.countInfo();
        build.remove(-1);
        build.remove(1);
        build.remove(2);
        JSONArray jsonArrayBuild = new JSONArray(10001);

        for (Map.Entry<Integer, JSONArray> entry : build.entrySet()) {
            jsonArrayBuild.addAll(entry.getValue());
        }

        JSONArray jsonArray = jsonObject.getJSONArray("features");
        for (int i = 0; i < jsonArrayBuild.size(); i++) {
            JSONObject jsonObject1 = jsonArrayBuild.getJSONObject(i);
            JSONArray geo = jsonObject1.getJSONArray("coordinates");
            int row = geo.size();
            JSONArray gpsList = new JSONArray();
            for (int h = 0; h < row; h++) {
                JSONArray temp = geo.getJSONArray(h);
                int temRow=temp.size();
                for(int j=0;j<temRow;j++) {
                    JSONArray tempV2=temp.getJSONArray(j);
                    double[] gps2 = new double[2];
                    gps2[0] = tempV2.getDouble(0);
                    gps2[1] = tempV2.getDouble(1);
                    gpsList.add(gps2);
                }
            }
            addLingString(jsonArray, i, 1, "LineString", gpsList);
        }
        return jsonObject;
    }


    public static void writerFoFile(String data) {
        try {
            String folderPath = "E:\\ownCode\\UMA\\uam\\地图工具-路网";
            File folder = new File(folderPath);
            String fileName = "\\polylineData1.js";
            if (!folder.exists()) {
                boolean result = folder.mkdirs();
            }
            BufferedWriter bufferedWriter = CommWriterFileInfo.getWriterBuffer(folderPath + "\\" + fileName, false);
            CommWriterFileInfo.writer(bufferedWriter, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static JSONObject dataDraw(List<List<Coordinate>> list, Bounds bounds, List<List<List<Coordinate>>> listInfo, boolean flag, boolean isDelArea) {
        JSONObject jsonObject = new JSONObject();
        JSONArray jsonArray = new JSONArray(1024);
        jsonObject.put("type", "GeometryCollection");
        if (flag) {
            for (int i = 0; i < listInfo.size(); i++) {
                list.addAll(listInfo.get(i));
            }
        }


        int row = list.size();
        String geoType = "LineString";
        for (int i = 0; i < row; i++) {
            jsonArray.addAll(setXYGeo(i, 0, list.get(i), geoType));
        }

        if (isDelArea) {
            //拿出数据，去掉空洞部分
            int dataIndexSize = listBuildInfo.size();
            for (int i = 0; i < dataIndexSize; i++) {
                jsonArray = dataInfo(jsonArray, listBuildInfo.get(i), geoType);
            }
        }
        jsonObject.put("features", jsonArray);
        return jsonObject;
    }

    /**
     * 去除空洞部分
     *
     * @param updateInfo updateInfo 全局数据
     * @param geometry   空洞边界
     * @return 空洞后的线
     */
    public static JSONArray dataInfo(JSONArray updateInfo, Geometry geometry, String geoType) {
        JSONArray jsonArray = new JSONArray(1024);
        int indexSize = updateInfo.size();
        for (int i = 0; i < indexSize; i++) {
            JSONArray points = updateInfo.getJSONObject(i).getJSONObject("geometry").getJSONArray("coordinates");
            int coordRow = points.size();
            StringBuffer stringBuffer = new StringBuffer();
            JSONArray gpsListAll = new JSONArray(coordRow);
            for (int h = 0; h < coordRow; h++) {
                JSONArray coordinate = points.getJSONArray(h);
                double[] gps = new double[2];
                gps[0] = coordinate.getDouble(0);
                gps[1] = coordinate.getDouble(1);
                stringBuffer.append(gps[0] + "," + gps[1] + ";");
                gpsListAll.add(gps);
            }
            String dataInfo = stringBuffer.substring(0, stringBuffer.length() - 1);

            Geometry line = defaultBuffer.geometrySplit(dataInfo);
            Geometry geometryIn = line.intersection(geometry);
            if (!geometryIn.isEmpty()) {
                JSONArray gpsList = new JSONArray(coordRow);
                Coordinate[] coordinates1 = geometryIn.getBoundary().getCoordinates();
                for (int h = 0; h < coordRow; h++) {
                    JSONArray array = points.getJSONArray(h);
                    boolean flag = GeoTools.onLineSegment(new Coordinate(array.getDouble(0), array.getDouble(1)), coordinates1[0], coordinates1[1]);
                    if (flag) {
                        JSONArray gps = gpsList.getJSONArray(gpsList.size() - 1);
                        double distance1 = GeoTools.distance(new Coordinate(gps.getDouble(0), gps.getDouble(1)), coordinates1[0]);
                        double distance2 = GeoTools.distance(new Coordinate(gps.getDouble(0), gps.getDouble(1)), coordinates1[1]);

                        double[] gps1 = new double[2];
                        gps1[0] = coordinates1[0].x;
                        gps1[1] = coordinates1[0].y;

                        double[] gps2 = new double[2];
                        gps2[0] = coordinates1[1].x;
                        gps2[1] = coordinates1[1].y;

                        gpsList.add(distance1 <= distance2 ? gps1 : gps2);
                        addLingString(jsonArray, i, 0, geoType, gpsList);
                        addLingString(jsonArray, i, 1 + 1, geoType, addOther(h, points, coordRow, !(distance1 <= distance2) ? gps1 : gps2, coordinates1));
                        break;
                    }
                    gpsList.add(array);
                }
            } else {
                addLingString(jsonArray, i, 0, geoType, gpsListAll);
            }
        }
        return jsonArray;
    }

    public static JSONArray addOther(int h, JSONArray array, int coordRow, double[] statGps, Coordinate[] coordinates1) {
        JSONArray gpsList = new JSONArray(1024);
        gpsList.add(statGps);
        for (int x = h + 1; x < coordRow; x++) {
            JSONArray jsonArray = array.getJSONArray(x);
            boolean flag = GeoTools.onLineSegment(new Coordinate(jsonArray.getDouble(0), jsonArray.getDouble(1)), coordinates1[0], coordinates1[1]);
            if (!flag) {
                gpsList.add(jsonArray);
            }
        }
        return gpsList;
    }

    public static void addLingString(JSONArray jsonArray, int i, int j, String geoType, JSONArray gpsList) {
        JSONObject geo = new JSONObject(4);
        geo.put("type", "Feature");
        JSONObject geoPro = new JSONObject(1);
        geoPro.put("name", i > 0 ? j + "-" + i : "area");
        geo.put("properties", geoPro);
        JSONObject objectInfo = new JSONObject();
        objectInfo.put("coordinates", gpsList);
        objectInfo.put("type", geoType);
        geo.put("geometry", objectInfo);
        jsonArray.add(geo);
    }

    public static JSONArray setXYGeo(int i, int j, List<Coordinate> list, String geoType) {
        JSONArray jsonArray = new JSONArray(1024);
        Coordinate[] coordinates = list.toArray(new Coordinate[0]);
        int coordRow = coordinates.length;
        JSONArray gpsList = new JSONArray(coordRow);
        for (int h = 0; h < coordRow; h++) {
            Coordinate coordinate = coordinates[h];
            double[] gps = new double[2];
            gps[0] = coordinate.x;
            gps[1] = coordinate.y;
            gpsList.add(gps);
        }
        addLingString(jsonArray, i, j, geoType, gpsList);
        return jsonArray;
    }
}
